import { useCallback, useContext, useEffect, useRef, useState } from "react";
import imageBoxLightIcon from "../images/Img_box_light.svg";
import Button from "react-bootstrap/Button";
import ButtonGroup from "react-bootstrap/ButtonGroup";
import styles from "./styles.module.scss";
import { WEBSOCKET_URL, getCvmodelNameList } from "../../api";
import { IsTestingContext, datasetContext } from "./context";

const RESULTS_FOR_SHOW = 5;
interface Result {
  image: string;
  cvmodel: string;
}

function TestResults() {
  const { isTesting } = useContext(IsTestingContext);
  const { dataset } = useContext(datasetContext);
  const [cvmodelNameList, setCvmodelNameList] = useState<string[]>([]);
  const [curResultIndex, setCurResultIndex] = useState(0);

  const ref = useRef<HTMLDivElement>(document.createElement("div"));
  const results = useRef<Result[]>([]);

  const displayResults = useCallback(() => {
    ref.current.innerHTML = "";
    results.current
      .slice(curResultIndex, curResultIndex + RESULTS_FOR_SHOW)
      .forEach(({ image, cvmodel }) => {
        const row = document.createElement("div");
        row.className = styles.row;
        // 添加输入图片
        const input = createImgItem(
          `/test/file?type=input&dataset=${dataset}&&image=${image}`
        );
        row.appendChild(input);
        // 添加输出图片
        cvmodelNameList.forEach((modelName) => {
          const isActive = modelName === cvmodel;
          const output = createImgItem(
            `/test/file?type=output&dataset=${dataset}&&cvmodel=${modelName}&&image=${image}`,
            isActive
          );
          row.appendChild(output);
        });
        ref.current.appendChild(row);
      });
  }, [curResultIndex, cvmodelNameList, dataset]);

  // 获取输出模型列表
  useEffect(() => {
    let ignore = false;
    getCvmodelNameList().then((data) => {
      if (!ignore) setCvmodelNameList(data);
    });
    return () => {
      ignore = true;
    };
  }, []);

  useEffect(() => {
    const ws = new WebSocket(WEBSOCKET_URL + "?task=test&monitor=result");
    ws.onmessage = (e) => {
      const result = JSON.parse(e.data);
      results.current.push(result);
    };
    return () => {
      ws.close();
    };
  });

  // 初始化
  useEffect(() => {
    if (isTesting) {
      results.current = [];
      setCurResultIndex(0);
      ref.current.innerHTML = "";
    }
    if (!isTesting && results.current.length > 0) {
      displayResults();
    }
  }, [displayResults, isTesting]);

  return (
    <div className={`${styles.results} ${styles.myCard}`}>
      <h5>
        <img alt="" src={imageBoxLightIcon}></img>测试结果
      </h5>
      <div className={styles.head}>
        <div className={styles.row}>
          <div className={styles.item}>输入</div>
          {cvmodelNameList.map((item) => {
            return (
              <div key={item} className={styles.item}>
                {item}
              </div>
            );
          })}
        </div>
      </div>
      <div id="photo-wall" className={styles.photoWall} ref={ref}></div>
      <div className={styles.footer}>
        {results.current.length > 0 && !isTesting && (
          <>
            <ButtonGroup>
              <Button
                variant="primary"
                onClick={() => {
                  setCurResultIndex((value) => value - RESULTS_FOR_SHOW);
                  displayResults();
                  ref.current.scrollTop = 0;
                }}
                disabled={curResultIndex - RESULTS_FOR_SHOW < 0}
              >
                上一组
              </Button>
              <Button
                variant="primary"
                onClick={() => {
                  setCurResultIndex((value) => value + RESULTS_FOR_SHOW);
                  displayResults();
                  ref.current.scrollTop = 0;
                }}
                disabled={
                  curResultIndex + RESULTS_FOR_SHOW >= results.current.length
                }
              >
                下一组
              </Button>
            </ButtonGroup>
            {`${curResultIndex / RESULTS_FOR_SHOW + 1} / ${Math.ceil(
              results.current.length / RESULTS_FOR_SHOW
            )}`}
          </>
        )}
      </div>
    </div>
  );
}

const createImgItem = (url: string, active: boolean = false): HTMLElement => {
  const item = document.createElement("item");
  item.className = styles.item;
  const image = document.createElement("img");
  image.className = active ? styles.active : "";
  image.src = url;
  item.appendChild(image);
  return item;
};

export default TestResults;
export type { Result };
